package com.example.config;

import com.example.filter.*;
import com.example.security.CustomAuthenticationProvider;
import com.example.service.CommonHttpService;
import com.example.service.CustomUserDetailsService;
import com.example.util.JwtUtil;
import com.example.util.SignatureUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig {

    private final CommonHttpService commonHttpService;
    private final ProxyConfig proxyConfig;
    @Lazy
    private final CustomUserDetailsService userDetailsService;
    private final JwtUtil jwtUtil;
    private final StringRedisTemplate redisTemplate;
    private final CustomAuthenticationProvider customAuthenticationProvider;
    private final SignatureUtil signatureUtil;
    private final EncryptionConfig encryptionConfig;
    private final ObjectMapper objectMapper;  // 用于处理 JSON

    // 通过配置文件注入开关值
    @Value("${security.signature.enabled}")
    private boolean signatureEnabled;

    @Value("${security.jwt.enabled}")
    private boolean jwtEnabled;

    @Value("${security.signature.expire.time}")
    private long signatureExpireTime;

    public SecurityConfig(CommonHttpService commonHttpService, ProxyConfig proxyConfig, CustomUserDetailsService userDetailsService, JwtUtil jwtUtil, StringRedisTemplate redisTemplate, CustomAuthenticationProvider customAuthenticationProvider, SignatureUtil signatureUtil, EncryptionConfig encryptionConfig, ObjectMapper objectMapper) {
        this.commonHttpService = commonHttpService;
        this.proxyConfig = proxyConfig;
        this.userDetailsService = userDetailsService;
        this.jwtUtil = jwtUtil;
        this.redisTemplate = redisTemplate;
        this.customAuthenticationProvider = customAuthenticationProvider;
        this.signatureUtil = signatureUtil;
        this.encryptionConfig = encryptionConfig;
        this.objectMapper = objectMapper;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 手动创建各个过滤器实例，并通过构造函数注入开关值
        TraceIdFilter traceIdFilter = new TraceIdFilter();
        CachingRequestResponseFilter cachingRequestResponseFilter = new CachingRequestResponseFilter();
        RequestLoggingFilter requestLoggingFilter = new RequestLoggingFilter();
        SignatureFilter signatureFilter = new SignatureFilter(signatureEnabled, signatureUtil, signatureExpireTime);  // 注入签名验证开关、工具类和过期时间
        JwtTokenFilter jwtTokenFilter = new JwtTokenFilter(jwtUtil, redisTemplate, userDetailsService, jwtEnabled);  // 注入 JWT 开关
        ProxyFilter proxyFilter = new ProxyFilter(commonHttpService, proxyConfig);
        RequestDecryptFilter requestDecryptFilter = new RequestDecryptFilter(encryptionConfig, objectMapper);
        ResponseEncryptFilter responseEncryptFilter = new ResponseEncryptFilter(encryptionConfig);

        http
                .csrf().disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)  // 无状态认证
                .and()
                .authorizeRequests()
                .antMatchers("/auth/login").permitAll()  // 放行登录请求
                .anyRequest().authenticated();  // 其他请求需要认证

        // 添加自定义过滤器到过滤器链
        http.addFilterBefore(traceIdFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(cachingRequestResponseFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(requestLoggingFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(signatureFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(proxyFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(requestDecryptFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(responseEncryptFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        return customAuthenticationProvider;
    }
}
